package excel.task;


import context.TaskContext;
import event.LogEvent;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import tasklog.LogEventPublisher;
import tasklog.LogQueue;
import tasklog.TaskLogDetailEvent;
import tasklog.TaskLogEvent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * 任务默认实现类：</br>
 * <p>
 * 1、任务异步执行时返回null，同步执行返回Object</br> 2、实现任务日志记录
 *
 * @author mei
 *
 *     </br>泛型定义：T返回类型     V参数类型
 */

@Component
public abstract class AbstractDefaultTask<T, V> {

    @Autowired
    LogEventPublisher publisher;

    @Autowired
    @Qualifier("cloudAsync")
    Executor executor;

    private Logger logger = LoggerFactory.getLogger(AbstractDefaultTask.class);

    /**
     * 当前线程局部任务对象
     */
    private ThreadLocal<TaskContext> localTaskContext = new ThreadLocal<TaskContext>();

    /**
     * 任务执行方法
     *
     * @param param   业务参数
     * @param isAsync true 异步执行 false 同步执行
     * @return 异步执行返回null，同步执行返回Object
     */
    public Object execute(V param, boolean isAsync) {
        try {
            if (isAsync) {
                executor.execute(new TaskThread<T, V>(this, param) {
                    @Override
                    protected void callException(Exception e) {
                        TaskContext task = localTaskContext.get();
                        logger.error("任务出现系统异常 task:{}", task, e);
                        if (task != null) {
                            fail(task, "任务出现系统异常:" + e.getMessage());
                        }
                    }
                });

                return null;
            } else {
                return execute(param);
            }
        } catch (Exception e) {
            TaskContext task = localTaskContext.get();
            logger.error("任务出现系统异常 task:{}", task, e);
            if (task != null) {
                fail(task, "任务出现系统异常:" + e.getMessage());
            }
        }

        return null;
    }

    /**
     * 任务失败时更新
     *
     * @param taskContext
     * @param content
     */
    protected void fail(TaskContext taskContext, String result) {
        localTaskContext.set(taskContext);

        TaskLogEvent taskLogEvent = TaskLogEvent.fail(taskContext, result);
        LogEvent<TaskLogEvent> event = new LogEvent<>(LogQueue.TASK_LOG_QUEUE, taskLogEvent);
        publisher.publish(event);
    }

    /**
     * 具体业务执行方法
     *
     * @param param 业务参数
     * @return 返回泛型中指定的类型
     */
    protected abstract T execute(V param);

    /**
     * 创建新任务消息
     *
     * @param taskContext
     * @param content
     */
    @Deprecated
    protected void working(TaskContext taskContext, String content) {
        localTaskContext.set(taskContext);

        TaskLogEvent taskLogEvent = TaskLogEvent.working(taskContext, content);
        LogEvent<TaskLogEvent> event = new LogEvent<>(LogQueue.TASK_LOG_QUEUE, taskLogEvent);
        publisher.publish(event);
    }

    /**
     * 创建新任务
     *
     * @param taskContext
     */
    protected void working(TaskContext taskContext) {
        localTaskContext.set(taskContext);

        TaskLogEvent taskLogEvent = TaskLogEvent.working(taskContext);
        LogEvent<TaskLogEvent> event = new LogEvent<>(LogQueue.TASK_LOG_QUEUE, taskLogEvent);
        publisher.publish(event);
    }

    /**
     * 任务成功时更新
     *
     * @param taskContext
     * @param result
     */
    protected void success(TaskContext taskContext, String result) {
        localTaskContext.set(taskContext);

        TaskLogEvent taskLogEvent = TaskLogEvent.success(taskContext, result);
        LogEvent<TaskLogEvent> event = new LogEvent<>(LogQueue.TASK_LOG_QUEUE, taskLogEvent);
        publisher.publish(event);
    }

    /**
     * 任务成功时更新
     *
     * @param taskContext
     * @param result      执行结果
     * @param url         文件存放的url
     */
    protected void success(TaskContext taskContext, String result, String url) {
        localTaskContext.set(taskContext);

        TaskLogEvent taskLogEvent = TaskLogEvent.success(taskContext, result, url);
        LogEvent<TaskLogEvent> event = new LogEvent<>(LogQueue.TASK_LOG_QUEUE, taskLogEvent);
        publisher.publish(event);
    }

    /**
     * 记录任务明细
     *
     * @param taskId
     * @param content
     */
    protected void taskDetail(Long taskId, String content) {
        LogEvent<TaskLogDetailEvent> eventDetail =
            new LogEvent<>(LogQueue.TASK_LOG_DETAIL_QUEUE, new TaskLogDetailEvent(taskId, content));
        publisher.publish(eventDetail);
    }

    /**
     * 批量记录任务明细
     *
     * @param taskId
     * @param contents
     */
    protected void batchTaskDetail(Long taskId, List<String> contents) {
        if (CollectionUtils.isNotEmpty(contents)) {
            List<TaskLogDetailEvent> details = new ArrayList<>();
            for (String content : contents) {
                details.add(new TaskLogDetailEvent(taskId, content));
            }
            LogEvent<List<TaskLogDetailEvent>> eventDetails =
                new LogEvent<>(LogQueue.BATCH_TASK_LOG_DETAIL_QUEUE, details);
            publisher.publish(eventDetails);
        }
    }
}
